﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Numerics;
using System.Reflection;
using System.Runtime.Intrinsics.Arm;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;

namespace MySoftLab.DapFlashCore.CoreSight
{
    /// <summary>
    /// Supported versions of APs
    /// </summary>
    public enum APVersion
    {
        // APv1 from ADIv5.x.
        APv1 = 1,
        // APv2 from ADIv6.
        APv2 = 2
    }

    /// <summary>
    /// An instance of this class has a "nominal address", which is an integer address in terms of how
    /// it is typically referenced.For instance, for an APv1, the nominal address is the unshifted
    /// APSEL, e.g. 0, 1, 2, and so on.This value is accessible by the _nominal_address_ property.It
    /// is also used for hashing and ordering.One intentional side effect of this is that APAddress
    /// instances match against the integer value of their nominal address, which is particularly useful
    /// when they are keys in a dictionary.

    /// In addition to the nominal address, there is an abstract _address_ property implemented by the
    /// version-specific subclasses.This is the value used by the DP hardware and passed to the
    /// DebugPort's read_ap() and write_ap() methods.

    /// AP addresses include the index of the DP to which the AP is connected.On most systems there is only
    /// one DP with index 0.

    /// The class also indicates which version of AP is targeted: either APv1 or APv2.The _ap_version_
    /// property reports this version number, though it is also encoded by the subclass.The AP version
    /// is coupled with the address because the two are intrinsically connected; the version defines the
    /// address format.
    /// </summary>
    public abstract class APAddressBase
    {
        public const int APSEL_SHIFT = 24;

        // Offset of IDR register in an APv1.
        public const uint AP_IDR = 0xFC;
        // Offset of IDR register in an APv2.
        public const uint APv2_IDR = 0xDFC;

        protected uint _nominalAddress;
        private uint _dp;

        public APAddressBase(uint address, uint dp = 0)
        {
            _nominalAddress = address;
            _dp = dp;
        }

        public abstract APVersion APVersion
        {
            get;
        }

        public uint NominalAddress { get => _nominalAddress; set => _nominalAddress = value; }

        public abstract uint Address
        {
            get;
        }

        public abstract uint IdrAddress
        {
            get;
        }

        public uint DpIndex { get => _dp; set => _dp = value; }
    }
}
